import Icon, { ClearOutlined } from '@ant-design/icons';
import { FloatButton } from 'antd';
import type { LngLatLike } from 'mapbox-gl';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type { Mapless } from '@/components/MapView';
import MapboxPopup, {
  type MapboxPopupRef,
} from '@/components/MapView/components/MapboxPopup/Index';
import { throttle } from '@/components/MapView/Mapless/core/throttle';
import type { Station } from '@/components/MapView/Mapless/index.d';
import PaintBoard from '@/components/MapView/Mapless/paint';
import {
  calculateObjectsInPolygon,
  getPaintCenter,
  type Paint,
  type PaintMode,
} from '@/components/MapView/Mapless/paint/utils';
import circleSvg from '../../icons/circle-select.svg?react';
import freedomSvg from '../../icons/freedom-select.svg?react';
import pointerSvg from '../../icons/pointer-select.svg?react';
import rectangleSvg from '../../icons/rectangle-select.svg?react';
import selectToolSvg from '../../icons/select-tool.svg?react';
import { getFunc } from '../../StationFuncAdapter';
import type { IconType } from '../index.d';
import styles from '../index.module.less';

// TODO 有点乱，需要优化
const SelectTool: React.FC<{
  mapless: Mapless | undefined;
  statioinFuncPrefix?: string;
  relativeManagerIds?: string[] | undefined;
  reset?: number;
  disabled?: boolean;
  onSelectionChange?: (selected: Station[] | undefined) => void;
  children?: React.ReactNode;
}> = (props) => {
  const {
    mapless,
    reset,
    statioinFuncPrefix = '',
    relativeManagerIds = ['sm1'],
    onSelectionChange,
    disabled = false,
    children,
  } = props;

  const [selectMode, setSelectMode] = useState<string>('selectTool');

  const paintRef = useRef<PaintBoard>(undefined);
  const paintsMapRef = useRef<Map<Paint, Station[] | undefined>>(new Map());
  const popupRef = useRef<MapboxPopupRef>(null);
  const maplessRef = useRef<Mapless>(undefined);

  const [selected, setSelected] = useState<Station[] | undefined>(undefined);
  const [position, setPosition] = useState<LngLatLike | undefined>();

  useEffect(() => {
    if (reset && reset > 0) {
      mapless?.interactionLayers(true);
      paintRef.current?.exitDraw();
      setSelectMode('selectTool');
    }
  }, [reset]);

  const updateSelected = () => {
    const m1Id = relativeManagerIds?.[0] || '';
    if (m1Id) {
      const sman = getFunc(statioinFuncPrefix)(mapless, m1Id);

      const allSelected = [...paintsMapRef.current.values()]
        .flat()
        .map((s) => s?.id);
      sman?.updateSelectedList(allSelected);
    }
  };

  const emitManaEvent = (selected: Station[]) => {
    const sman = getFunc(statioinFuncPrefix)(
      mapless,
      relativeManagerIds?.[0] || '',
    );
    sman?.emitEvent('stationsSelected', selected, 'SelectTool');
  };

  useEffect(() => {
    if (mapless) {
      // TODO 保留图层，并添加点击事件
      paintRef.current = new PaintBoard(mapless, { maxCount: 3 });
      paintRef.current.onDrawing = throttle((paint) => {
        const p = paint as Paint;
        if (p) {
          const sman = getFunc(statioinFuncPrefix)(
            mapless,
            relativeManagerIds?.[0] || '',
          );
          const stations = sman?.getStations();
          const selected = calculateObjectsInPolygon<Station>(stations, p);
          paintsMapRef.current.set(p, selected);
        } else {
          // TODO what?
        }
        updateSelected();
      }, 100);

      paintRef.current.onDrawingEnd = (paint) => {
        const p = paint as Paint;
        if (p) {
          const selected = paintsMapRef.current.get(p);
          setSelected(selected);
          const pc = getPaintCenter(p);
          setPosition(pc);
          popupRef.current?.show();
          onSelectionChange?.(selected);
          emitManaEvent(selected || []);
        } else {
          // TODO what?
        }
      };

      paintRef.current.onDrawingRemove = (paint) => {
        paint && paintsMapRef.current.delete(paint);
        updateSelected();
        onSelectionChange?.([]);
        emitManaEvent([]);
      };

      maplessRef.current = mapless;
    }
  }, [mapless]);

  useEffect(() => {
    return () => {
      // 移除绘制工具
      paintRef.current?.destroy();
    };
  }, []);

  const icons: IconType = useMemo(
    () => ({
      selectTool: <Icon component={selectToolSvg} />,
      select: <Icon component={pointerSvg} />,
      circle: <Icon component={circleSvg} />,
      rectangle: <Icon component={rectangleSvg} />,
      freedom: <Icon component={freedomSvg} />,
      select_s: (
        <Icon
          component={pointerSvg}
          style={{ color: 'var(--theme-color-primary)' }}
        />
      ),
      circle_s: (
        <Icon
          component={circleSvg}
          style={{ color: 'var(--theme-color-primary)' }}
        />
      ),
      rectangle_s: (
        <Icon
          component={rectangleSvg}
          style={{ color: 'var(--theme-color-primary)' }}
        />
      ),
      freedom_s: (
        <Icon
          component={freedomSvg}
          style={{ color: 'var(--theme-color-primary)' }}
        />
      ),
      clear: <ClearOutlined />,
    }),
    [],
  );

  const escapeHandler = useCallback((e: KeyboardEvent) => {
    if (e.key === 'Escape') {
      onModeClick('exit');
    }
  }, []);

  const onModeClick = (mode: string) => {
    if (mode === 'exit') {
      mapless?.interactionLayers(true);
      paintRef.current?.exitDraw();
      setSelectMode('selectTool');
      window.removeEventListener('keydown', escapeHandler);
      return;
    }
    if (mode === 'clear') {
      const sman = getFunc(statioinFuncPrefix)(
        mapless,
        relativeManagerIds?.[0] || '',
      );
      sman?.clearSelected();
      paintRef.current?.clearDraw();
      paintsMapRef.current = new Map();
      popupRef.current?.hide();
      // TODO 通知sm1清除选择
      updateSelected();
      onSelectionChange?.([]);
      emitManaEvent([]);
      return;
    }
    setSelectMode(mode);
    mapless?.interactionLayers(false);
    paintRef.current?.startDraw();
    paintRef.current?.setPaintMode(mode as PaintMode);
    window.addEventListener('keydown', escapeHandler);
  };

  return (
    <>
      <FloatButton.Group
        trigger="hover"
        shape="square"
        placement="right"
        className={styles.drawtool}
        tooltip={{
          title:
            selectMode === 'selectTool' ? '选择工具' : '点击或Esc取消选择模式',
          placement: 'left',
          rootClassName: styles.tooltip,
        }}
        icon={
          icons[selectMode === 'selectTool' ? selectMode : `${selectMode}_s`]
        }
        onClick={() => onModeClick('exit')}
      >
        <FloatButton
          icon={icons.select}
          tooltip="选择"
          onClick={() => onModeClick('select')}
        />
        <FloatButton
          icon={icons.circle}
          tooltip="圈选"
          className={disabled ? styles.selectDisabled : ''}
          onClick={() => onModeClick('circle')}
        />
        <FloatButton
          icon={icons.rectangle}
          tooltip="框选"
          className={disabled ? styles.selectDisabled : ''}
          onClick={() => onModeClick('rectangle')}
        />
        <FloatButton
          icon={icons.freedom}
          tooltip="自由"
          className={disabled ? styles.selectDisabled : ''}
          onClick={() => onModeClick('freedom')}
        />
        <FloatButton
          icon={icons.clear}
          tooltip="清除"
          onClick={() => onModeClick('clear')}
        />
      </FloatButton.Group>
      <MapboxPopup
        ref={popupRef}
        maplessRef={maplessRef}
        lngLat={position as LngLatLike}
      >
        {children ? (
          children
        ) : (
          <>
            <h4>
              已选站点
              {selected && selected?.length > 0 ? ` (${selected.length})` : ''}
            </h4>
            <div style={{ maxHeight: 200, overflow: 'auto' }}>
              {selected && selected?.length > 0 ? (
                selected.map((s) => <div key={s.id}>{s.name}</div>)
              ) : (
                <span>暂无数据</span>
              )}
            </div>
          </>
        )}
      </MapboxPopup>
    </>
  );
};

export default SelectTool;
